﻿using System.IO;
using System.Numerics;

namespace OpenSage.FileFormats.W3d;

/// <param name="Version"></param>
/// <param name="Attributes"></param>
/// <param name="MeshName"></param>
/// <param name="ContainerName"></param>
/// <param name="NumTris">number of triangles</param>
/// <param name="NumVertices">number of unique vertices</param>
/// <param name="NumMaterials">number of unique materials</param>
/// <param name="NumDamageStages">number of damage offset chunks</param>
/// <param name="SortLevel">static sorting level of this mesh</param>
/// <param name="PrelitVersion">mesh generated by this version of Lightmap Tool</param>
/// <param name="FutureCounts">future counts</param>
/// <param name="VertexChannels">bits for presence of types of per-vertex info</param>
/// <param name="FaceChannels">bits for presence of types of per-face info</param>
/// <param name="Min">Min corner of the bounding box</param>
/// <param name="Max">Max corner of the bounding box</param>
/// <param name="SphCenter">Center of bounding sphere</param>
/// <param name="SphRadius">Bounding sphere radius</param>
public sealed record W3dMeshHeader3(
    uint Version,
    W3dMeshFlags Attributes,
    string MeshName,
    string ContainerName,
    uint NumTris,
    uint NumVertices,
    uint NumMaterials,
    uint NumDamageStages,
    uint SortLevel,
    uint PrelitVersion,
    uint FutureCounts,
    W3dVertexChannels VertexChannels,
    W3dFaceChannels FaceChannels,
    Vector3 Min,
    Vector3 Max,
    Vector3 SphCenter,
    float SphRadius) : W3dChunk(W3dChunkType.W3D_CHUNK_MESH_HEADER3)
{
    // boundary values for W3dMeshHeaderStruct::SortLevel
    public const int SortLevelNone = 0;
    public const int SortLevelMax = 32;
    public const int SortLevelBin1 = 20;
    public const int SortLevelBin2 = 15;
    public const int SortLevelBin3 = 10;

    internal static W3dMeshHeader3 Parse(BinaryReader reader, W3dParseContext context)
    {
        return ParseChunk(reader, context, header =>
        {
            var version = reader.ReadUInt32();
            var attributes = reader.ReadUInt32AsEnumFlags<W3dMeshFlags>();
            var meshName = reader.ReadFixedLengthString(W3dConstants.NameLength);
            var containerName = reader.ReadFixedLengthString(W3dConstants.NameLength);
            var numTris = reader.ReadUInt32();
            var numVertices = reader.ReadUInt32();
            var numMaterials = reader.ReadUInt32();
            var numDamageStages = reader.ReadUInt32();
            var sortLevel = reader.ReadUInt32();
            var prelitVersion = reader.ReadUInt32();
            var futureCounts = reader.ReadUInt32();
            var vertexChannels = reader.ReadUInt32AsEnumFlags<W3dVertexChannels>();
            var faceChannels = reader.ReadUInt32AsEnum<W3dFaceChannels>();
            var min = reader.ReadVector3();
            var max = reader.ReadVector3();
            var sphCenter = reader.ReadVector3();
            var sphRadius = reader.ReadSingle();

            return new W3dMeshHeader3(version, attributes, meshName, containerName, numTris, numVertices, numMaterials,
                numDamageStages, sortLevel, prelitVersion, futureCounts, vertexChannels, faceChannels, min, max,
                sphCenter, sphRadius);
        });
    }

    protected override void WriteToOverride(BinaryWriter writer)
    {
        writer.Write(Version);
        writer.Write((uint)Attributes);
        writer.WriteFixedLengthString(MeshName, W3dConstants.NameLength);
        writer.WriteFixedLengthString(ContainerName, W3dConstants.NameLength);
        writer.Write(NumTris);
        writer.Write(NumVertices);
        writer.Write(NumMaterials);
        writer.Write(NumDamageStages);
        writer.Write(SortLevel);
        writer.Write(PrelitVersion);
        writer.Write(FutureCounts);
        writer.Write((uint)VertexChannels);
        writer.Write((uint)FaceChannels);
        writer.Write(Min);
        writer.Write(Max);
        writer.Write(SphCenter);
        writer.Write(SphRadius);
    }
}
